// Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]

mod ssh;
mod terminal;
mod config;
mod security;
mod tunnel;

use tauri::{Manager, Emitter};
use std::sync::Arc;
use tokio::sync::Mutex;
use tauri::async_runtime;
use log::{info, error, debug};
use std::collections::HashMap;
use std::process::{Stdio};
use tokio::process::{Child, Command as TokioCommand};
use tokio::io::{AsyncReadExt, AsyncWriteExt, BufReader};
use std::sync::atomic::{AtomicU32, Ordering};
use uuid::Uuid;

// 本地终端进程管理
#[derive(Debug)]
struct LocalTerminal {
    id: String,
    process: Arc<Mutex<Option<Child>>>,
    stdin: Arc<Mutex<Option<tokio::process::ChildStdin>>>,
}

// 应用状态
struct AppState {
    connections: Arc<Mutex<Vec<ssh::SshConnection>>>,
    config: Arc<Mutex<Option<config::ConfigManager>>>,
    terminal_manager: Arc<Mutex<Option<terminal::TerminalManager>>>,
    local_terminals: Arc<Mutex<HashMap<String, LocalTerminal>>>,
}

impl Default for AppState {
    fn default() -> Self {
        Self {
            connections: Arc::new(Mutex::new(Vec::new())),
            config: Arc::new(Mutex::new(None)),
            terminal_manager: Arc::new(Mutex::new(None)),
            local_terminals: Arc::new(Mutex::new(HashMap::new())),
        }
    }
}

// 用于前端响应的SSH连接结构体
#[derive(Debug, Clone, serde::Serialize)]
struct ConnectionStatus {
    status: String,
    message: Option<String>,
}

#[derive(Debug, Clone, serde::Serialize)]
struct SshConnectionResponse {
    id: String,
    config: ssh::SshConfig,
    status: ConnectionStatus,
    created_at: String,
    connected_at: Option<String>,
    last_activity: Option<String>,
    error_message: Option<String>,
}

// Tauri命令
#[tauri::command]
async fn create_ssh_connection(
    host: String,
    port: u16,
    username: String,
    auth_method: serde_json::Value,
    state: tauri::State<'_, AppState>,
    app_handle: tauri::AppHandle,
) -> Result<SshConnectionResponse, String> {
    // 调试：打印接收到的认证方法数据
    println!("收到SSH连接请求:");
    println!("  主机: {}:{}", host, port);
    println!("  用户名: {}", username);
    println!("  认证方法原始数据: {}", serde_json::to_string_pretty(&auth_method).unwrap_or_else(|_| "无法序列化".to_string()));
    
    // 解析认证方法
    let ssh_auth = if let Some(auth_type) = auth_method.get("type").and_then(|v| v.as_str()) {
        println!("  解析到的认证类型: {}", auth_type);
        match auth_type {
            "password" => {
                let password = auth_method.get("data")
                    .and_then(|d| d.get("password"))
                    .and_then(|p| p.as_str())
                    .unwrap_or("")
                    .to_string();
                println!("  密码认证，密码长度: {}", password.len());
                ssh::AuthMethod::Password(password)
            }
            "public_key" => {
                let private_key_path = auth_method.get("data")
                    .and_then(|d| d.get("private_key_path"))
                    .and_then(|p| p.as_str())
                    .unwrap_or("")
                    .to_string();
                let passphrase = auth_method.get("data")
                    .and_then(|d| d.get("passphrase"))
                    .and_then(|p| p.as_str())
                    .map(|s| s.to_string());
                println!("  公钥认证，私钥路径: {}, 有密码: {}", private_key_path, passphrase.is_some());
                ssh::AuthMethod::PublicKey { private_key_path, passphrase }
            }
            "agent" => {
                println!("  SSH Agent认证");
                ssh::AuthMethod::Agent
            }
            _ => {
                println!("  不支持的认证方式: {}", auth_type);
                return Err(format!("不支持的认证方式: {}", auth_type));
            }
        }
    } else {
        return Err("无效的认证方法格式".to_string());
    };
    
    // 创建SSH配置
    let ssh_config = ssh::SshConfig {
        host: host.clone(),
        port,
        username: username.clone(),
        auth_method: ssh_auth,
        password: None,
        private_key_path: None,
        connect_timeout: Some(30),
        keepalive_interval: Some(60),
    };
    
    // 生成连接ID - 使用基于host、port、username的唯一标识
    let connection_id = ssh::utils::generate_connection_id(&host, port, &username);
    
    // 创建连接配置
    let connection_config = config::ConnectionConfig {
        id: connection_id.clone(),
        name: format!("{}@{}:{}", username, host, port),
        ssh_config: ssh_config.clone(),
        tunnels: Vec::new(),
        terminal_config: config::TerminalConfigOverride::default(),
        tags: Vec::new(),
        notes: None,
        use_count: 0,
        created_at: chrono::Utc::now(),
        last_used: None,
    };
    
    let connection = ssh::SshConnection::new(connection_config);
    
    match connection.connect().await {
        Ok(()) => {
            let mut connections = state.connections.lock().await;
            let now = chrono::Utc::now().to_rfc3339();
            
            info!("SSH连接成功，连接ID: {}", connection.id);
            
            // 发送连接成功日志
            let _ = app_handle.emit("terminal-log", serde_json::json!({
                "level": "info",
                "message": format!("SSH连接成功: {}@{}:{}", username, host, port),
                "source": "ssh",
                "connection_id": connection.id
            }));
            
            // 保存连接配置到持久化存储
            {
                info!("开始保存连接配置: {}", connection.id);
                let mut config_guard = state.config.lock().await;
                if let Some(config_manager) = config_guard.as_mut() {
                    info!("配置管理器已获取，准备保存连接: {}", connection.config.name);
                    if let Err(e) = config_manager.save_connection(connection.config.clone()).await {
                        error!("保存连接配置失败: {}", e);
                        // 发送保存失败日志，但不影响连接成功的返回
                        let _ = app_handle.emit("terminal-log", serde_json::json!({
                            "level": "warn",
                            "message": format!("连接成功但保存配置失败: {}", e),
                            "source": "config",
                            "connection_id": connection.id
                        }));
                    } else {
                        info!("连接配置已成功保存: {} ({})", connection.id, connection.config.name);
                        // 发送保存成功日志
                        let _ = app_handle.emit("terminal-log", serde_json::json!({
                            "level": "info",
                            "message": format!("连接配置已保存到本地: {}", connection.config.name),
                            "source": "config",
                            "connection_id": connection.id
                        }));
                    }
                } else {
                    error!("配置管理器未初始化，无法保存连接配置");
                    let _ = app_handle.emit("terminal-log", serde_json::json!({
                        "level": "error",
                        "message": "配置管理器未初始化，无法保存连接配置",
                        "source": "config",
                        "connection_id": connection.id
                    }));
                }
            }
            
            let response = SshConnectionResponse {
                id: connection.id.clone(),
                config: ssh_config.clone(),
                status: ConnectionStatus {
                    status: "connected".to_string(),
                    message: Some("SSH连接已建立".to_string()),
                },
                created_at: now.clone(),
                connected_at: Some(now.clone()),
                last_activity: Some(now),
                error_message: None,
            };
            connections.push(connection);
            Ok(response)
        }
        Err(e) => {
            error!("SSH连接失败: {}", e);
            
            // 发送连接失败日志
            let _ = app_handle.emit("terminal-log", serde_json::json!({
                "level": "error",
                "message": format!("SSH连接失败: {}", e),
                "source": "ssh",
                "host": format!("{}:{}", host, port)
            }));
            
            let now = chrono::Utc::now().to_rfc3339();
            let response = SshConnectionResponse {
                id: connection.id.clone(),
                config: ssh_config,
                status: ConnectionStatus {
                    status: "error".to_string(),
                    message: Some(format!("连接失败: {}", e)),
                },
                created_at: now.clone(),
                connected_at: None,
                last_activity: None,
                error_message: Some(e.to_string()),
            };
            Ok(response)
        }
    }
}

#[tauri::command]
async fn create_tunnel(
    connection_id: String,
    local_port: u16,
    remote_host: String,
    remote_port: u16,
    tunnel_type: String,
    _state: tauri::State<'_, AppState>,
) -> Result<String, String> {
    tunnel::create_tunnel(
        connection_id,
        local_port,
        remote_host,
        remote_port,
        tunnel_type,
    ).await.map_err(|e| format!("创建隧道失败: {}", e))
}

#[tauri::command]
async fn save_connection_config(
    config: config::ConnectionConfig,
    state: tauri::State<'_, AppState>,
) -> Result<(), String> {
    let mut config_guard = state.config.lock().await;
    let config_manager = config_guard.as_mut().ok_or("配置管理器未初始化")?;
    config_manager.save_connection(config).await
        .map_err(|e| format!("保存配置失败: {}", e))
}

#[tauri::command]
async fn get_saved_connections(
    state: tauri::State<'_, AppState>,
) -> Result<Vec<config::ConnectionConfig>, String> {
    info!("前端请求获取已保存的连接列表");
    let config_guard = state.config.lock().await;
    let config = config_guard.as_ref().ok_or("配置管理器未初始化")?;
    let connections = config.get_all_connections().into_iter().cloned().collect::<Vec<_>>();
    info!("返回 {} 个已保存的连接配置", connections.len());
    for conn in &connections {
        info!("连接配置: {} ({})", conn.id, conn.name);
    }
    Ok(connections)
}

#[tauri::command]
async fn delete_connection_config(
    connection_id: String,
    state: tauri::State<'_, AppState>,
) -> Result<(), String> {
    let mut config_guard = state.config.lock().await;
    let config = config_guard.as_mut().ok_or("配置管理器未初始化")?;
    config.delete_connection(&connection_id).await
        .map_err(|e| format!("删除配置失败: {}", e))
}

// 终端相关命令
#[tauri::command]
async fn create_terminal(
    connection_id: String,
    command: Option<String>,
    state: tauri::State<'_, AppState>,
    app_handle: tauri::AppHandle,
) -> Result<String, String> {
    info!("创建终端会话: connection_id={}, command={:?}", connection_id, command);
    
    // 获取SSH连接的会话
    let ssh_session = {
        let connections = state.connections.lock().await;
        let connection = connections.iter()
            .find(|conn| conn.id == connection_id)
            .ok_or_else(|| format!("连接 {} 不存在", connection_id))?;
        
        // 检查SSH会话是否存在
        {
            let session_guard = connection.session.lock().await;
            if session_guard.is_none() {
                return Err("SSH会话未建立".to_string());
            }
        }
        
        // 直接使用连接中的session
        connection.session.clone()
    };
    
    // 获取终端管理器
    let terminal_manager = {
        let manager_guard = state.terminal_manager.lock().await;
        manager_guard.as_ref()
            .ok_or("终端管理器未初始化")?
            .clone()
    };
    
    // 获取连接名称
    let connection_name = {
        let connections = state.connections.lock().await;
        connections.iter()
            .find(|conn| conn.id == connection_id)
            .map(|conn| conn.config.name.clone())
            .unwrap_or_else(|| "Unknown".to_string())
    };
    
    // 创建终端配置
    let terminal_config = terminal::TerminalConfig::new(
        format!("Terminal - {}", connection_name),
        connection_id.clone()
    )
    .with_size(terminal::TerminalSize {
        cols: 80,
        rows: 24,
        width_px: 640,
        height_px: 384,
    })
    .with_shell(command.unwrap_or_else(|| "/bin/bash".to_string()));
    
    let terminal_id = terminal_config.id.clone();
    
    // 创建终端实例
    match terminal_manager.create_terminal(terminal_config).await {
        Ok(_) => {
            // 连接终端到SSH会话
            // 从Option<Session>中提取Session并包装为Arc<Mutex<Session>>
            let session_arc = {
                let session_guard = ssh_session.lock().await;
                let session = session_guard.as_ref()
                    .ok_or("SSH会话未建立")?;
                Arc::new(Mutex::new(session.clone()))
            };
            
            match terminal_manager.connect_terminal(&terminal_id, session_arc).await {
                Ok(()) => {
                    info!("终端创建并连接成功: {}", terminal_id);
                    
                    // 启动终端事件监听
                    let app_handle_clone = app_handle.clone();
                    let terminal_manager_clone = terminal_manager.clone();
                    let terminal_id_clone = terminal_id.clone();
                    
                    tauri::async_runtime::spawn(async move {
                        if let Ok(mut event_receiver) = terminal_manager_clone.get_terminal_events(&terminal_id_clone).await {
                            while let Some(event) = event_receiver.recv().await {
                                match event {
                                    terminal::TerminalEvent::Output(data) => {
                                        let output_str = String::from_utf8_lossy(&data).to_string();
                                        let _ = app_handle_clone.emit("terminal-output", serde_json::json!({
                                            "terminal_id": terminal_id_clone,
                                            "type": "data",
                                            "data": output_str
                                        }));
                                        
                                        // 发送日志事件
                                        let _ = app_handle_clone.emit("terminal-log", serde_json::json!({
                                            "level": "debug",
                                            "message": format!("接收数据: {}字节", data.len()),
                                            "source": "terminal",
                                            "terminal_id": terminal_id_clone
                                        }));
                                    }
                                    terminal::TerminalEvent::Input(data) => {
                                        let input_str = String::from_utf8_lossy(&data).to_string();
                                        let _ = app_handle_clone.emit("terminal-log", serde_json::json!({
                                            "level": "debug",
                                            "message": format!("发送输入: {}", input_str.trim()),
                                            "source": "terminal",
                                            "terminal_id": terminal_id_clone
                                        }));
                                    }
                                    terminal::TerminalEvent::ConnectionChanged(connected) => {
                                        let status = if connected { "已连接" } else { "已断开" };
                                        let _ = app_handle_clone.emit("terminal-log", serde_json::json!({
                                            "level": "info",
                                            "message": format!("终端连接状态: {}", status),
                                            "source": "connection",
                                            "terminal_id": terminal_id_clone
                                        }));
                                    }
                                    terminal::TerminalEvent::Error(error_msg) => {
                                        let _ = app_handle_clone.emit("terminal-log", serde_json::json!({
                                            "level": "error",
                                            "message": format!("终端错误: {}", error_msg),
                                            "source": "terminal",
                                            "terminal_id": terminal_id_clone
                                        }));
                                    }
                                    terminal::TerminalEvent::Resize(size) => {
                                        let _ = app_handle_clone.emit("terminal-log", serde_json::json!({
                                            "level": "info",
                                            "message": format!("终端大小调整: {}x{}", size.cols, size.rows),
                                            "source": "terminal",
                                            "terminal_id": terminal_id_clone
                                        }));
                                    }
                                    terminal::TerminalEvent::Closed => {
                                        let _ = app_handle_clone.emit("terminal-log", serde_json::json!({
                                            "level": "info",
                                            "message": "终端会话已关闭",
                                            "source": "terminal",
                                            "terminal_id": terminal_id_clone
                                        }));
                                        break;
                                    }
                                }
                            }
                        }
                    });
                    
                    Ok(terminal_id)
                }
                Err(e) => {
                    error!("连接终端失败: {}", e);
                    // 清理已创建的终端
                    let _ = terminal_manager.remove_terminal(&terminal_id).await;
                    Err(format!("连接终端失败: {}", e))
                }
            }
        }
        Err(e) => {
            error!("创建终端失败: {}", e);
            Err(format!("创建终端失败: {}", e))
        }
    }
}

#[tauri::command]
async fn terminal_input(
    terminal_id: String,
    data: String,
    state: tauri::State<'_, AppState>,
) -> Result<(), String> {
    // 添加详细的调试日志
    println!("[DEBUG] terminal_input 被调用:");
    println!("  terminal_id: {}", terminal_id);
    println!("  data_len: {}", data.len());
    println!("  data_bytes: {:?}", data.as_bytes());
    println!("  data_repr: {:?}", data);
    
    debug!("终端输入: terminal_id={}, data_len={}, data={:?}", terminal_id, data.len(), data);
    
    let terminal_manager = {
        let manager_guard = state.terminal_manager.lock().await;
        manager_guard.as_ref()
            .ok_or("终端管理器未初始化")?
            .clone()
    };
    
    println!("[DEBUG] 准备发送数据到终端管理器");
    match terminal_manager.send_input(&terminal_id, data.as_bytes()).await {
        Ok(()) => {
            println!("[DEBUG] 终端输入发送成功: {}", terminal_id);
            debug!("终端输入发送成功: {}", terminal_id);
            Ok(())
        }
        Err(e) => {
            println!("[ERROR] 发送终端输入失败: {}", e);
            error!("发送终端输入失败: {}", e);
            Err(format!("发送输入失败: {}", e))
        }
    }
}

#[tauri::command]
async fn terminal_resize(
    terminal_id: String,
    size: terminal::TerminalSize,
    state: tauri::State<'_, AppState>,
) -> Result<(), String> {
    debug!("终端大小调整: terminal_id={}, size={:?}", terminal_id, size);
    
    let terminal_manager = {
        let manager_guard = state.terminal_manager.lock().await;
        manager_guard.as_ref()
            .ok_or("终端管理器未初始化")?
            .clone()
    };
    
    match terminal_manager.resize_terminal(&terminal_id, size).await {
        Ok(()) => {
            debug!("终端大小调整成功: {}", terminal_id);
            Ok(())
        }
        Err(e) => {
            error!("调整终端大小失败: {}", e);
            Err(format!("调整大小失败: {}", e))
        }
    }
}

#[tauri::command]
async fn close_terminal(
    terminal_id: String,
    state: tauri::State<'_, AppState>,
) -> Result<(), String> {
    info!("关闭终端: {}", terminal_id);
    
    let terminal_manager = {
        let manager_guard = state.terminal_manager.lock().await;
        manager_guard.as_ref()
            .ok_or("终端管理器未初始化")?
            .clone()
    };
    
    match terminal_manager.remove_terminal(&terminal_id).await {
        Ok(()) => {
            info!("终端关闭成功: {}", terminal_id);
            Ok(())
        }
        Err(e) => {
            error!("关闭终端失败: {}", e);
            Err(format!("关闭终端失败: {}", e))
        }
    }
}

// 本地终端相关命令
#[tauri::command]
async fn create_local_terminal(
    state: tauri::State<'_, AppState>,
    app_handle: tauri::AppHandle,
) -> Result<String, String> {
    info!("创建本地终端");
    
    let terminal_id = Uuid::new_v4().to_string();
    
    // 创建本地shell进程
    let mut cmd = TokioCommand::new("/bin/zsh");
    cmd.stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .stderr(Stdio::piped())
        .env("TERM", "xterm-256color")
        .env("PS1", "$ ");
    
    match cmd.spawn() {
        Ok(mut child) => {
            let stdin = child.stdin.take();
            let stdout = child.stdout.take();
            let stderr = child.stderr.take();
            
            let local_terminal = LocalTerminal {
                id: terminal_id.clone(),
                process: Arc::new(Mutex::new(Some(child))),
                stdin: Arc::new(Mutex::new(stdin)),
            };
            
            // 保存到状态中
            {
                let mut terminals = state.local_terminals.lock().await;
                terminals.insert(terminal_id.clone(), local_terminal);
            }
            
            // 启动输出监听
            if let Some(stdout) = stdout {
                let app_handle_clone = app_handle.clone();
                let terminal_id_clone = terminal_id.clone();
                
                tokio::spawn(async move {
                    let mut reader = BufReader::new(stdout);
                    let mut buffer = [0; 1024];
                    
                    loop {
                        match reader.read(&mut buffer).await {
                            Ok(0) => break, // EOF
                            Ok(n) => {
                                let data = String::from_utf8_lossy(&buffer[..n]).to_string();
                                let _ = app_handle_clone.emit("local-terminal-output", serde_json::json!({
                                    "terminal_id": terminal_id_clone,
                                    "data": data
                                }));
                            }
                            Err(e) => {
                                error!("读取本地终端输出失败: {}", e);
                                break;
                            }
                        }
                    }
                });
            }
            
            // 启动错误输出监听
            if let Some(stderr) = stderr {
                let app_handle_clone = app_handle.clone();
                let terminal_id_clone = terminal_id.clone();
                
                tokio::spawn(async move {
                    let mut reader = BufReader::new(stderr);
                    let mut buffer = [0; 1024];
                    
                    loop {
                        match reader.read(&mut buffer).await {
                            Ok(0) => break, // EOF
                            Ok(n) => {
                                let data = String::from_utf8_lossy(&buffer[..n]).to_string();
                                let _ = app_handle_clone.emit("local-terminal-output", serde_json::json!({
                                    "terminal_id": terminal_id_clone,
                                    "data": data
                                }));
                            }
                            Err(e) => {
                                error!("读取本地终端错误输出失败: {}", e);
                                break;
                            }
                        }
                    }
                });
            }
            
            info!("本地终端创建成功: {}", terminal_id);
            Ok(terminal_id)
        }
        Err(e) => {
            error!("创建本地终端失败: {}", e);
            Err(format!("创建本地终端失败: {}", e))
        }
    }
}

#[tauri::command]
async fn local_terminal_input(
    terminal_id: String,
    data: String,
    state: tauri::State<'_, AppState>,
) -> Result<(), String> {
    debug!("本地终端输入: terminal_id={}, data={:?}", terminal_id, data);
    
    let terminals = state.local_terminals.lock().await;
    if let Some(terminal) = terminals.get(&terminal_id) {
        let mut stdin_guard = terminal.stdin.lock().await;
        if let Some(stdin) = stdin_guard.as_mut() {
            match stdin.write_all(data.as_bytes()).await {
                Ok(()) => {
                    if let Err(e) = stdin.flush().await {
                        error!("刷新本地终端输入失败: {}", e);
                        return Err(format!("刷新输入失败: {}", e));
                    }
                    debug!("本地终端输入发送成功: {}", terminal_id);
                    Ok(())
                }
                Err(e) => {
                    error!("发送本地终端输入失败: {}", e);
                    Err(format!("发送输入失败: {}", e))
                }
            }
        } else {
            Err("本地终端stdin未初始化".to_string())
        }
    } else {
        Err(format!("本地终端 {} 不存在", terminal_id))
    }
}

#[tauri::command]
async fn close_local_terminal(
    terminal_id: String,
    state: tauri::State<'_, AppState>,
) -> Result<(), String> {
    info!("关闭本地终端: {}", terminal_id);
    
    let mut terminals = state.local_terminals.lock().await;
    if let Some(terminal) = terminals.remove(&terminal_id) {
        // 关闭stdin
        {
            let mut stdin_guard = terminal.stdin.lock().await;
            if let Some(mut stdin) = stdin_guard.take() {
                let _ = stdin.shutdown().await;
            }
        }
        
        // 终止进程
        {
            let mut process_guard = terminal.process.lock().await;
            if let Some(mut process) = process_guard.take() {
                let _ = process.kill().await;
                let _ = process.wait().await;
            }
        }
        
        info!("本地终端关闭成功: {}", terminal_id);
        Ok(())
    } else {
        Err(format!("本地终端 {} 不存在", terminal_id))
    }
}

fn main() {
    env_logger::init();
    
    tauri::Builder::default()
        .plugin(tauri_plugin_shell::init())
        .manage(AppState::default())
        .invoke_handler(tauri::generate_handler![
            create_ssh_connection,
            create_tunnel,
            save_connection_config,
            get_saved_connections,
            delete_connection_config,
            create_terminal,
            terminal_input,
            terminal_resize,
            close_terminal,
            create_local_terminal,
            local_terminal_input,
            close_local_terminal
        ])
        .setup(|app| {
            // 初始化应用配置
            let app_handle = app.handle().clone();
            
            tauri::async_runtime::spawn(async move {
                let state: tauri::State<AppState> = app_handle.state();
                match config::ConfigManager::new().await {
                    Ok(config_manager) => {
                        let mut config = state.config.lock().await;
                        *config = Some(config_manager);
                    }
                    Err(e) => {
                        log::error!("初始化配置管理器失败: {}", e);
                    }
                }
                
                // 初始化终端管理器
                let mut terminal_manager_guard = state.terminal_manager.lock().await;
                if terminal_manager_guard.is_none() {
                    *terminal_manager_guard = Some(terminal::TerminalManager::new());
                }
            });
            
            Ok(())
        })
        .run(tauri::generate_context!())
        .expect("启动应用失败");
}